namespace HZY.Framework.DependencyInjection.Attributes;

/// <summary>
/// 配置文件属性注入 配置文件中 value 如果是 $(xxxKey) 这种格式 ，那么自动去读取环境变量
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor, AllowMultiple = false, Inherited = true),
 Pointcut("ctor(*())")]
public class ConfigurationPropertiesAttribute : AopMoAttribute
{
    public ConfigurationPropertiesAttribute()
    {
    }

    public ConfigurationPropertiesAttribute(string prefix)
    {
        Prefix = prefix;
    }

    /// <summary>
    /// 前缀
    /// </summary>
    private string? Prefix { get; }

    public override void OnSuccess(MethodContext context)
    {
        // 如果是 构造函数
        if (context.Method.IsConstructor)
        {
            var target = context.Target;
            var targetType = context.TargetType;

            var propertyInfos = targetType.GetProperties();
            foreach (var item in propertyInfos)
            {
                // 获取属性的配置文件注入
                if (GetValue(context, item.PropertyType, item.Name, out var r))
                {
                    return;
                }

                if (r is null)
                {
                    Debug.WriteLine("Final result is null after processing.");
                    return;
                }

                item.SetValue(target, r);
            }

            return;
        }

        if (context.ReturnType == null)
        {
            Debug.WriteLine("Method has no return type.");
            return;
        }

        var name = context.Method.Name;
        if (!name.StartsWith("get_"))
        {
            Debug.WriteLine("Method is not a getter.");
            return;
        }

        name = name.Replace("get_", "");

        if (GetValue(context, context.ReturnType, name, out var result))
        {
            return;
        }

        if (result is null)
        {
            Debug.WriteLine("Final result is null after processing.");
            return;
        }

        context.ReplaceReturnValue(this, result);
    }

    private bool GetValue(MethodContext context, Type returnType, string name, out object? result)
    {
        var configuration = AopMoAttribute.WebApplicationBuilder?.Configuration ??
                            this.GetService<IConfiguration>(context)
            ;

        // 读取 configuration
        result = configuration?.GetSection(this.GetKey(name)).Get(returnType);

        if (result is null)
        {
            Debug.WriteLine($"Configuration value for key '{this.GetKey(name)}' is null.");
            return true;
        }

        if (result is string envKeyString)
        {
            // 判断获取的值 是否是这样的 $(xxxKey) 那么是读取环境变量
            if ((envKeyString.StartsWith("$(") && envKeyString.EndsWith($")")) ||
                (envKeyString.StartsWith("${") && envKeyString.EndsWith(new StringBuilder().Append('}').ToString())))
            {
                var envKey = envKeyString.Replace("$(", "");
                envKey = envKey.Replace(")", "");
                envKey = envKey.Replace("${", "");
                envKey = envKey.Replace("}", "");

                result = Environment.GetEnvironmentVariable(envKey);
                if (result is null)
                {
                    Debug.WriteLine($"Environment variable for key '{envKey}' is null.");
                }
            }
        }

        if (result is null)
        {
            Debug.WriteLine("Final result is null after processing.");
            return true;
        }

        return false;
    }

    /// <summary>
    /// 获取 key 的完整路径
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    private string GetKey(string key)
    {
        return string.IsNullOrWhiteSpace(Prefix) ? key : $"{Prefix}:{key}";
    }
}